import { Injectable } from '@angular/core';
import { HttpService } from 'service/HttpService';
import { Observable } from 'rxjs/Observable';

@Injectable()
export class ChartService {
  constructor(private httpService:HttpService) {

  }

  getHistoryData(params) {
    return this.httpService.get('/api/quote/GetHistoricalQuote', params);
  }

  getCandleData(data) {
    const candleList = [];
    const timeList = data.Time;
    const open = data.Open;
    const close = data.Close;
    const high = data.High;
    const low = data.Low;
    const count = timeList.length;
    for (let i=0; i<count; i++) {
      const dayData = [];
      dayData.push(open[i]);
      dayData.push(close[i]);
      dayData.push(low[i]);
      dayData.push(high[i]);
      candleList.push(dayData);
    }
    return candleList;
  }

  getMAData(dataList, day) {
    const maList = []; 
    const count = dataList.length;
    for(let i=0; i<count; i++) {
      if(i < day) {
        let sum = 0;
        for(let j=0; j<=i; j++) {
          sum+=dataList[j];
        }
        maList.push((sum/(i+1)).toFixed(2));
        continue;
      }
      let sum = 0;
      for(let j=1; j<=day; j++) {
        sum+=dataList[i-j];
      }
      maList.push((sum/day).toFixed(2));
    }

    return maList;
  }

  cacuBoll(list, day, k, start, end) {
    let ma = 0;
    let up = 0;
    let down = 0;

    let maSum = 0;
    for(let j=start; j<=end; j++) {
      maSum+=list[j];
    }
    
    ma = parseFloat((maSum/day).toFixed(2));

    let mdSum = 0;
    for(let j=start; j<=end; j++) {
      mdSum += Math.pow(list[start] - ma, 2);
    }

    let md = Math.sqrt(mdSum/day);

    up = parseFloat((ma + k*md).toFixed(2));
    down = parseFloat((ma - k*md).toFixed(2));

    return [ma, up, down];
  }

  getBollData(dataList, day, k) {
    const mbList = [];
    const upList = [];
    const downList = [];

    const count = dataList.length;
    for(let i=0; i<count; i++) {
      if(i < day) {
        const data = this.cacuBoll(dataList, day, k, 0, i);
        mbList.push(data[0]);
        upList.push(data[1]);
        downList.push(data[2]);
        continue;
      }

      const data = this.cacuBoll(dataList, day, k, i-day, i);
      mbList.push(data[0]);
      upList.push(data[1]);
      downList.push(data[2]);
    }

    return [mbList, upList, downList];
  }

  cacuRSI(close, open, start, end) {

    let upSum = 0;
    let downSum = 0;

    let rsi = 50.00;

    if(start === end) {
      return rsi;
    }

    for(let j=start; j<=end; j++) {
      if ((close[j] - open[j]) > 0) {
        upSum += (close[j] - open[j]); 
      } else {
        downSum += (open[j] - close[j]);
      }
    }
    
    if (downSum === 0 && upSum === 0) {
      rsi = 50.00;
    } else if (downSum === 0 && upSum !== 0) {
      rsi = 100.00;
    } else {
      const rs = ((upSum/(end-start)) / (downSum/(end-start))).toFixed(3);
      rsi = parseFloat((100 * parseFloat(rs)/(1 + parseFloat(rs))).toFixed(2));
    }

    return rsi;
  }

  getRSIData(data, day) {
    const close = data.Close;
    const open  = data.Open;
    const count = close.length;
    const rsiList = [];
    for(let i=0; i<count; i++) {
      if(i < day) {
        rsiList.push(this.cacuRSI(close, open, 0, i));
        continue;
      }

      rsiList.push(this.cacuRSI(close, open, i-day, i));
    }

    return rsiList;
  }

  cacuBias(list, start, end) {
      let sum = 0;

      if(start === end) {
        return null;
      }

      for(let j=start; j<=end; j++) {
        sum+=list[j];
      }
      

      let average = sum / (end - start);
      let bias = ((list[end] - average) / average * 100).toFixed(3);
      return parseFloat(bias);
  }

  getBIASData(dataList, day) {
    const biasList = []; 
    const count = dataList.length;

    for(let i=0; i<count; i++) {
      if(i < day) {
        biasList.push(this.cacuBias(dataList, 0, i));
        continue;
      }
      biasList.push(this.cacuBias(dataList, i - day, i));
    }

    return biasList;
  }

  getPSYData(data, day) {
    const close = data.Close;
    const open  = data.Open;
    const count = close.length;
    const psyList = [];

    for(let i=0; i<count; i++) {
      if(i < day) {
        psyList.push(null);
        continue;
      }

      let upSum = 0;

      for(let j=1; j<=day; j++) {
        if ((close[i-j] - open[i-j]) > 0) {
          upSum++; 
        } 
      }
      
      const psy = ((upSum/day) * 100).toFixed(1);
      psyList.push(psy);      
    }

    return psyList;
  }

  getEMAData(dataList, day) {
    const emaList = [];
    const count = dataList.length;
    const x = 2 / (day + 1);
    
    for (let i=0; i<count; i++) {
      if (i == 0) {
        emaList.push(dataList[i]);
        continue;
      } 
      const ema = x*dataList[i] + (1-x)*emaList[i-1];
      emaList.push(parseFloat(ema.toFixed(2)));
    }
    return emaList;
  }

  getMACDData(dataList, lday, sday, mday) {
    const lemaList = this.getEMAData(dataList, lday);
    const semaList = this.getEMAData(dataList, sday);
    const difList = [];
    const deaList = [];
    const macdList = [];
    const count = dataList.length;
    const x = 2 / (mday + 1);

    for(let i=0; i<count; i++) {
      const dif = semaList[i] -lemaList[i];
      difList.push(dif.toFixed(4));
      if (i == 0) {
        deaList.push(dataList[i]);
        continue;
      }

      const dea = deaList[i-1] * (1-x) + x*dif;
      deaList.push(dea.toFixed(4));
      const macd = dif - dea;
      macdList.push(macd.toFixed(4)) * 2;
    }

    return {
      dif: difList,
      dea: deaList,
      macd: macdList
    };
  }
}